package edu.washington.cs.cmdsynth.gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.UIManager;
import javax.swing.WindowConstants;

public class GUIMain extends JFrame {
	
	private static final long serialVersionUID = 7577576909102362657L;

	private GUIController controller = new GUIController();
	
	//UI widgets that need to respond to certain UI events
	private JComboBox manualKindBox = null;
	private JPanel checkboxPanel = null;
	private JButton addButton = null;
	private JButton readButton = null;
	private JComboBox exampleList = null;
	private JTextField inputField = null;
	private JButton actionButton = null;
	private JList outputList = null;
	private DefaultListModel listModel=new DefaultListModel();
	
	private final JFileChooser fc = new JFileChooser();
	
	//the size of each component
	private int containerWidth = 970;
	private int containerHeight = 480;
	private int outputPanelWidth = 250;
	private int outputPanelHeight = 380;
	private int manualPanelWidth = 240;
	private int manualPanelHeight = 390;
	
	public GUIMain() {
		initComponents();
		initEventHandlers();
	}
	
	private void initComponents() {
		//construct the left part
		JLabel manualLabel = new JLabel(Labels.manual_format);
		this.manualKindBox = new JComboBox(BuiltInExamples.getExampleManualTypes());
		//the panel hosting manual items
		JScrollPane manualPanel = new JScrollPane();
		checkboxPanel = new JPanel();
		checkboxPanel.setLayout(new BoxLayout(checkboxPanel, BoxLayout.PAGE_AXIS));
		for(JCheckBox box : this.getManualList()) {
			checkboxPanel.add(box);
		}
		manualPanel.add(checkboxPanel);
		manualPanel.setPreferredSize(new Dimension(this.manualPanelWidth, this.manualPanelHeight));
		manualPanel.setViewportView(checkboxPanel);
		//two action buttons
		addButton = new JButton(Labels.add_manual);
		readButton = new JButton(Labels.read_manual);
		
		//construct the right parts
		JLabel sentencelabel = new JLabel(Labels.type_sentence);
		JLabel exampleLabel = new JLabel(Labels.example_sentence);
		exampleList = new JComboBox(BuiltInExamples.getExampleSentences());
        inputField = new JTextField();
        actionButton = new JButton(Labels.synthesize);
        JLabel resultLabel = new JLabel(Labels.output_title);
        //output list
        String[] examples = BuiltInExamples.getExampleSythesizedCommands();
        for (int i=0; i< examples.length; i++) {
          listModel.addElement(examples[i]);
        }
        outputList = new JList(listModel);
        outputList.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
        outputList.setLayoutOrientation(JList.VERTICAL);
        JScrollPane listScroller = new JScrollPane(outputList);
        listScroller.setPreferredSize(new Dimension(this.outputPanelWidth, this.outputPanelHeight));
        
        //put left, right UI elements to the panels
        JPanel leftPanel = new JPanel();
        BoxLayout leftLayout = new BoxLayout(leftPanel, BoxLayout.PAGE_AXIS);
        leftPanel.setLayout(leftLayout);
        
        JPanel leftTopPanel = new JPanel();
        leftTopPanel.add(manualLabel, BorderLayout.LINE_START);
        leftTopPanel.add(this.createEmptyLabel(5));
        leftTopPanel.add(this.manualKindBox, BorderLayout.LINE_END);
        
        JPanel leftButtomPanel = new JPanel();
        leftButtomPanel.add(addButton, BorderLayout.LINE_START);
        leftButtomPanel.add(this.createEmptyLabel(5));
        leftButtomPanel.add(readButton, BorderLayout.LINE_END);
        
        leftPanel.add(leftTopPanel);
        leftPanel.add(manualPanel);
        leftPanel.add(leftButtomPanel);

        JPanel rightPanel = new JPanel();
        BoxLayout rightLayout = new BoxLayout(rightPanel, BoxLayout.PAGE_AXIS);
        rightPanel.setLayout(rightLayout);       
        
        JPanel rightTopPanel = new JPanel();
        rightTopPanel.add(sentencelabel, BorderLayout.LINE_START);
        rightTopPanel.add(this.createEmptyLabel(11));
        rightTopPanel.add(exampleLabel);
        rightTopPanel.add(exampleList, BorderLayout.LINE_END);
        
        rightPanel.add(rightTopPanel);
        JPanel inputPanel = new JPanel();
        inputPanel.setLayout(new BoxLayout(inputPanel, BoxLayout.LINE_AXIS));
        inputPanel.add(inputField);
        inputPanel.add(this.createEmptyLabel(2));
        inputPanel.add(actionButton);
        rightPanel.add(inputPanel);
        rightPanel.add(this.createEmptyLabel());
        
        rightPanel.add(resultLabel);
        rightPanel.add(listScroller);
        
        leftPanel.setBorder(BorderFactory.createLineBorder(Color.WHITE, 10));
        rightPanel.setBorder(BorderFactory.createLineBorder(Color.WHITE, 10));
        
        Container container = this.getContentPane();
        container.setPreferredSize(new Dimension(this.containerWidth, this.containerHeight));
        container.add(leftPanel, BorderLayout.LINE_START);
        container.add(rightPanel, BorderLayout.LINE_END);
        
        setTitle(Labels.title);
        pack();
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
	}
	
	public void initEventHandlers() {
		this.addButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
            	int returnVal = fc.showOpenDialog(GUIMain.this);
                if (returnVal == JFileChooser.APPROVE_OPTION) {
                    File file = fc.getSelectedFile();
                    JOptionPane.showMessageDialog(null, "Add..", file.getName(), JOptionPane.PLAIN_MESSAGE);
                    checkboxPanel.add(new JCheckBox("test"));
                    checkboxPanel.revalidate();
                    checkboxPanel.repaint();
                } 
            }
        });
		this.readButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
            	Component[] comps = checkboxPanel.getComponents();
            	StringBuilder sb = new StringBuilder();
            	for(Component comp : comps) {
            		if(comp instanceof JCheckBox) {
            			JCheckBox checkBox = (JCheckBox)comp;
            			if(checkBox.isSelected()) {
            			    String text = checkBox.getText();
            			    sb.append(text);
            			    sb.append(" ");
            			}
            		}
            	}
            	JOptionPane.showMessageDialog(null, sb.toString(), "Final Runtime", JOptionPane.PLAIN_MESSAGE);
            }
        });
		this.actionButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
            	JOptionPane.showMessageDialog(null, "Start synthesized..", "Final Runtime", JOptionPane.PLAIN_MESSAGE);
            	String[] results = controller.synthesizeCommands(getInputText());
            	//populate to the JList
            	listModel.clear();
            	for(String result : results) {
            		listModel.addElement(result);
            	}
            }
        });
		exampleList.addActionListener (new ActionListener () {
		    public void actionPerformed(ActionEvent e) {
		        String selectedText = exampleList.getSelectedItem().toString();
		        inputField.setText(selectedText);
		    }
		});
		manualKindBox.addActionListener (new ActionListener () {
		    public void actionPerformed(ActionEvent e) {
		        String selectedText = manualKindBox.getSelectedItem().toString();
		        JOptionPane.showMessageDialog(null, selectedText, "Final Runtime", JOptionPane.PLAIN_MESSAGE);
		    }
		});
	}
	
	public String getInputText() {
		return this.inputField.getText();
	}
	
	private JCheckBox[] getManualList() {
		String[] texts = BuiltInExamples.getExampleManualNames();
		JCheckBox[] boxes = new JCheckBox[texts.length];
		for(int i = 0; i < texts.length; i++) {
			boxes[i] = new JCheckBox(texts[i]);
			boxes[i].setSelected(true);
		}
		return boxes;
	}
	
	private JLabel createEmptyLabel(int size) {
		StringBuilder sb = new StringBuilder();
		for(int i = 0; i < size; i++) {
			sb.append(" ");
		}
		return new JLabel(sb.toString());
	}
	
	private JLabel createEmptyLabel() {
		return this.createEmptyLabel(0);
	}
	
	public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
                new GUIMain().setVisible(true);
            }
        });
    }
}